前幾天我一路追著 RoomRush 的資料來源,把原本分散在不同檔案裡的流程串了起來:
SF.csv / ES.csv
↓
AppDatabase.parseCsv()
↓
ClassroomSchedule
↓
Room Database
↓
DAO
↓
Repository
↓
AppContainer
↓
ViewModel
↓
空教室查詢結果
這條流程讓我理解課表資料從哪裡來、怎麼存進資料庫,以及最後怎麼被查詢使用。
但當我開始準備往管理者功能看時,出現了一個新的問題:如果管理者要修改這些資料,修改後的資料會一直保留下來嗎? 這個問題讓我重新回頭看了資料庫初始化的流程。
這不是單純的猜測,而是從實際程式碼確認出的資料生命週期問題。
一開始看到 SF.csv、ES.csv 時,我很自然地把它們理解成:「App 第一次建立資料庫時,用來提供初始課表的資料。」
所以我的想法很簡單:
CSV
↓
建立初始資料
↓
Room Database
↓
之後 App 都從 Room 讀取
所以如果管理者修改了一間教室的資料,我直覺會認為:「那就把 Room 裡的資料改掉就好了。」
但問題是:CSV 還在那裡,如果 CSV 裡面的資料沒有跟著改,那它和資料庫裡的資料就可能開始不一樣。
回到程式碼:
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
triggerPopulate()
}
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
triggerPopulate()
}
流程:
onOpen()
↓
triggerPopulate()
↓
讀取 CSV
↓
parseCsv()
↓
dao.insertAll()
↓
REPLACE
我在 AppDatabase 裡看到,資料庫建立時的 onCreate() 和每次開啟資料庫時的 onOpen(),都會觸發預載資料的流程。
繼續追下去後,我發現 triggerPopulate() 會重新讀取 CSV,解析成 ClassroomSchedule,最後透過 DAO 寫回資料庫,而且這裡使用的是 REPLACE。
這才讓原本的問題變得明確:如果管理者修改過的資料和 CSV 不一樣,下一次重新匯入時,CSV 的資料就可能取代管理者修改後的資料。
先不管實際是哪一行程式碼,單純從「資料從哪裡來」來看:
SF.csv / ES.csv
↓
parseCsv()
↓
ClassroomSchedule
↓
DAO
↓
Room Database
管理者
↓
ViewModel
↓
Repository
↓
DAO
↓
Room Database
這時候真正的問題就出現了:
SF.csv / ES.csv
↓
Room Database
↑
│
管理者
「同一個資料庫,開始有兩個方向的資料來源。」
假設 CSV 一開始記錄:SF130 是普通教室。後來管理者進入後台,把 SF130 改成實驗室。
如果修改成功,現在資料庫裡是:
SF130 → 實驗室
但 CSV 裡還是:
SF130 → 一般教室
那如果某個時候 App 又重新載入 CSV:
SF130 到底應該是一般教室,還是實驗室?
這就是我覺得值得注意的地方。
因為這已經不是單純的「資料有沒有存成功」,而是:這個專案到底把誰當成資料的最終來源?
這次我沒有直接問 Hermes:「這段程式碼有什麼問題?」
而是讓它幫我把幾個分散的流程放在一起比較:
再回到實際程式碼逐一確認。
這次 AI 對我最大的幫助不是「告訴我答案」,而是幫我把原本分開看的兩條流程放到同一張圖裡。
今天我原本只是想繼續往下了解管理者功能,卻意外發現了資料生命週期上的問題。
前面我一直在追問:「資料怎麼流動?」;但今天開始,我第一次問:「資料到底是誰說了算?」
CSV 是課表的原始資料,而管理者又可以修改 Room Database 裡的資料。當我把這兩條寫入路徑放在一起後,才發現:資料能被寫進資料庫,不代表資料的生命週期就被設計好了。
更具體來說,目前 onOpen() 會重新觸發 CSV 匯入,而匯入使用 REPLACE,因此管理者修改過的資料可能在重新匯入後被原始 CSV 取代。
這不是單純某個畫面顯示錯誤,而是資料初始化與管理者修改之間,缺少明確資料生命週期策略的問題。
既然管理者可以修改 App 裡的重要資料,接下來就正式進入到第三階段-「管理者功能主線」,管理者到底可以修改哪些資料?誰有權限進行這些修改?
管理者功能的第一個入口就是登入功能- LoginActivity.kt,下一篇會介紹到:關於「管理者功能」到底是怎麼進來的?